package com.iteaj.iot.boot.autoconfigure;

import com.iteaj.iot.ChannelManager;
import com.iteaj.iot.ComponentFactory;
import com.iteaj.iot.IotThreadManager;
import com.iteaj.iot.boot.condition.ConditionalOnIotClient;
import com.iteaj.iot.boot.core.IotCoreConfiguration;
import com.iteaj.iot.business.ProtocolHandleFactory;
import com.iteaj.iot.client.http.HttpManager;
import com.iteaj.iot.client.http.okhttp.OkHttpManager;
import com.iteaj.iot.client.proxy.ProxyClientComponent;
import com.iteaj.iot.client.websocket.WebSocketClientListener;
import com.iteaj.iot.client.websocket.impl.DefaultWebSocketClientComponent;
import com.iteaj.iot.client.websocket.impl.DefaultWebSocketClientProtocolHandle;
import com.iteaj.iot.client.websocket.impl.DefaultWebSocketListenerManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;

import java.util.List;
import java.util.stream.Collectors;

@Order(88168)
@ConditionalOnIotClient
@AutoConfigureAfter(IotCoreConfiguration.class)
@EnableConfigurationProperties(IotClientProperties.class)
public class IotClientConfiguration implements InitializingBean, ApplicationContextAware {

    public static ApplicationContext applicationContext;

    private IotClientProperties properties;
    public static ChannelManager deviceManager;
    protected final IotThreadManager threadManager;
    private final ComponentFactory componentFactory;
    private final ProtocolHandleFactory protocolHandleFactory;

    private Logger logger = LoggerFactory.getLogger(IotClientConfiguration.class);

    public IotClientConfiguration(IotThreadManager threadManager, IotClientProperties properties
            , ComponentFactory componentFactory, ProtocolHandleFactory protocolHandleFactory) {
        this.properties = properties;
        this.threadManager = threadManager;
        this.componentFactory = componentFactory;
        this.protocolHandleFactory = protocolHandleFactory;
    }

//    @Override
//    public void run(ApplicationArguments args) throws Exception {
//        /**
//         * 只有在将客户端和服务端在同一个应用上下文的时候才会有设备管理
//         */
//        if(applicationContext.containsBean("deviceManager")) {
//            IotClientConfiguration.deviceManager = applicationContext.getBean(ChannelManager.class);
//        }
//
//        ClientComponentFactory instance = ClientComponentFactory.getInstance();
//        // 启动所有客户端组件
//        componentFactory.start(null);
//
//        // 启动超时管理器
//        this.clientProtocolTimeoutManager.start(null);
//
//        // 所有组件启动完成
//        instance.forEach(item -> item.finished());
//
//        logger.info("IOT客户端应用启动成功 启用组件数：{}", instance.getComponents().size());
//    }

    @Override
    public void afterPropertiesSet() throws Exception { }

//    @Bean("httpManager")
//    @ConditionalOnMissingBean(HttpManager.class)
    public HttpManager httpManager() {
        return new OkHttpManager();
    }

    /**
     * 发布应用事件
     * @param event
     */
    public static void publishApplicationEvent(ApplicationEvent event) {
        applicationContext.publishEvent(event);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        IotClientConfiguration.applicationContext = applicationContext;
    }

    @Bean
    @ConditionalOnExpression("${iot.client.proxy.start:false}")
    public ProxyClientComponent proxyClientComponent() {
        return new ProxyClientComponent(properties.getProxy());
    }

    @Bean
    @ConditionalOnBean(WebSocketClientListener.class)
    public DefaultWebSocketClientComponent defaultWebSocketClientComponent(ObjectProvider<WebSocketClientListener> listeners) {
        List<WebSocketClientListener> listenerList = listeners.stream().collect(Collectors.toList());
        return new DefaultWebSocketClientComponent(listenerList);
    }

    @Bean
    @ConditionalOnBean(WebSocketClientListener.class)
    public DefaultWebSocketClientProtocolHandle defaultWebSocketClientProtocolHandle(DefaultWebSocketClientComponent clientComponent) {
        return new DefaultWebSocketClientProtocolHandle(clientComponent);
    }

    @Bean
    @ConditionalOnBean(WebSocketClientListener.class)
    public DefaultWebSocketListenerManager defaultWebSocketListenerManager(List<WebSocketClientListener> listeners) {
        return new DefaultWebSocketListenerManager(listeners);
    }
}
